# 人类
# 属性(变量)：姓名、年龄、性别、身高、体重......
# 动作(方法)：玩、看、走......
# 类是显示世界中客观事物的一个抽象
# 对象它是某个类的具体实现
class Person():
    # self -> this 表示对象本身
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
        # 在python中没有访问的修饰符，没有private这种修饰符
        # 可以在定义属性名的时候，在属性名之前加上__
        # 但实际上 还是可以通过特定的方式取出来
        self.__secret = "这是" + name + "的秘密，不想告诉别人"

    def walk(self):
        print(self.name + "会走路")

    def see(self):
        print(self.name + "能看见世界")


# 人类特定的一个对象
# 创建了xiaoming对象
xiaoming = Person("小明", 20, "男")
print(xiaoming.name)
print(xiaoming.age)
print(xiaoming.gender)
xiaoming.walk()
xiaoming.see()
# 创建了xiaohua对象
xiaohua = Person("小花", 18, "女")
print(xiaohua.name)
print(xiaohua.age)
print(xiaohua.gender)
# __开头的属性不能直接取
# print(xiaohua.__secret)
# 但是可以通过_类名+属性名
print(xiaohua._Person__secret)
xiaohua.walk()
xiaohua.see()


# Person的__init__方法需要传入3个参数
# 这里只传了一个，所以会报错
# Person("小华")

# 定义一个Teacher类 -> 子类
# 继承自Person类 -> 父类
# 继承可以得到父类的所有属性及方法
class Teacher(Person):
    def __init__(self, name, age, gender, id):
        # super表示直接调用父类的初始化方法
        super(Teacher, self).__init__(name, age, gender)
        self.id = id

    def teaching(self):
        print("老师会上课")

    # 多态
    # 重新定义父类的方法
    def see(self):
        print("重新定义父类中的see方法")
        print("老师：" + self.name + "会看")


class Student(Person):
    def __init__(self, name, age, gender):
        super(Student, self).__init__(name, age, gender)

    def learning(self):
        print("学生会学习")

    # 重新定义父类的方法
    def see(self):
        print("学生：" + self.name + "会看")


teacher = Teacher("张老师", 24, "男", "00001")
print(teacher.name)
print(teacher.age)
print(teacher.gender)
print(teacher.id)
teacher.walk()
teacher.teaching()
student = Student("小华", 20, "男")
student.learning()

# 虽然Teacher、Student类都是Person的子类，都拥有see方法
# 但是在Teacher、Student类中都对see方法重新进行了定义
# 最终实例化出来的对象，虽然调用的都是see方法，但是表现出来的不一样
# 这就是多态
# 多态：同一操作作用于不同的对象，可以得到不同的解释，产生不同的执行结果
teacher.see()
student.see()
